const unqualifiedArea: string = "unqualified";//问题件摆放区域名称
const lift2: Array<string> = ["ALift", "BLift"];//2台电梯区域名称
const lift1: Array<string> = ["ALift"]; //1台电梯出库区域名称
const lift3: Array<string> = ["BLift"]; //1台电梯入库区域名称
const liftSiteCount: number = 4; //1台电梯库位数量
const localtionStateUrl: string = "http://localhost:8080/script-api/localtionState" //库位状态上传wms请求url
const qrCodeInformationUrl: string = "http://localhost:8080/script-api/qrCodeInformation" //扫码信息请求url
// ============================== Configurations Start ==============================
/**
 * PLC 的相关配置，生产环境中，请根据现场的实际情况进行配置。
 * 
 * 【注意】
 *  - 配置 PLC 的参数之前，请先用 ModbusTcp 调试工具，例如 Modbus Poll，对 PLC 进行调试，以确认 PLC 的相关参数是否正常！！！
 * 
 */
const plcConfig = {
    qrIp: "127.0.0.1",              // PLC 的 IP 地址
    qrPort: 501,                     // PLC 监听的端口号
    qrSlaveId: 1,                     // PLC 中设置的 slaveId。
    qrInitWrite: {             // “扫码器初始化指令”的信号的地址信息
        type: "4x",                 // 地址类型
        number: 0,                  // 地址编号
        mark: "扫码器初始化指令"      // 地址说明
    },
    qrInitRead: {           // “扫码器初始化是否完成”的信号的地址信息
        type: "3x",
        number: 0,
        mark: "扫码器初始化是否完成"
    },
    qrWrite: {            // “触发扫码”的信号的地址信息
        type: "4x",
        number: 1,
        mark: "触发扫码"
    },
    qrRead: {            // “是否完成扫码”的信号的地址信息
        type: "3x",
        number: 1,
        mark: "是否完成扫码"
    },
    remarkLift: {            // “标记入库电梯为出库电梯”的信号的地址信息
        type: "4x",
        number: 2,
        mark: "标记入库电梯为出库电梯"
    },
    qrcode: {            // “查询二维码字符串”的信号的地址信息
        type: "3x",
        number: 3,
        count: 20,
        mark: "查询二维码字符串"
    },
    ALiftIp: "127.0.0.1",              // PLC 的 IP 地址
    ALiftPort: 503,                     // PLC 监听的端口号
    ALiftSlaveId: 1,                     // PLC 中设置的 slaveId
    BLiftIp: "127.0.0.1",              // PLC 的 IP 地址
    BLiftPort: 504,                     // PLC 监听的端口号
    BLiftSlaveId: 1,                     // PLC 中设置的 slaveId
    liftOpenFloor1: {            // “电梯开门层数指令”的信号的地址信息
        type: "4x",
        number: 0,
        mark: "1楼电梯开门层数指令"
    },
    liftOpenFloor2: {            // “电梯开门层数指令”的信号的地址信息
        type: "4x",
        number: 4,
        mark: "2楼电梯开门层数指令"
    },
    liftOpenFloor3: {            // “电梯开门层数指令”的信号的地址信息
        type: "4x",
        number: 8,
        mark: "3楼电梯开门层数指令"
    },
    liftOpenFloor4: {            // “电梯开门层数指令”的信号的地址信息
        type: "4x",
        number: 12,
        mark: "4楼电梯开门层数指令"
    },
    liftOpenFloor5: {            // “电梯开门层数指令”的信号的地址信息
        type: "4x",
        number: 16,
        mark: "5楼电梯开门层数指令"
    },
    liftOpen1: {            // “电梯开门指令”的信号的地址信息
        type: "4x",
        number: 1,
        mark: "1楼电梯开门指令"
    },
    liftOpen2: {            // “电梯开门指令”的信号的地址信息
        type: "4x",
        number: 5,
        mark: "2楼电梯开门指令"
    },
    liftOpen3: {            // “电梯开门指令”的信号的地址信息
        type: "4x",
        number: 9,
        mark: "3楼电梯开门指令"
    },
    liftOpen4: {            // “电梯开门指令”的信号的地址信息
        type: "4x",
        number: 13,
        mark: "4楼电梯开门指令"
    },
    liftOpen5: {            // “电梯开门指令”的信号的地址信息
        type: "4x",
        number: 17,
        mark: "5楼电梯开门指令"
    },
    liftCloseFloor1: {            // “电梯关门层数指令”的信号的地址信息
        type: "4x",
        number: 2,
        mark: "1楼电梯关门层数指令"
    },
    liftCloseFloor2: {            // “电梯关门层数指令”的信号的地址信息
        type: "4x",
        number: 6,
        mark: "2楼电梯关门层数指令"
    },
    liftCloseFloor3: {            // “电梯关门层数指令”的信号的地址信息
        type: "4x",
        number: 10,
        mark: "3楼电梯关门层数指令"
    },
    liftCloseFloor4: {            // “电梯关门层数指令”的信号的地址信息
        type: "4x",
        number: 14,
        mark: "4楼电梯关门层数指令"
    },
    liftCloseFloor5: {            // “电梯关门层数指令”的信号的地址信息
        type: "4x",
        number: 18,
        mark: "5楼电梯关门层数指令"
    },
    liftClose1: {            // “电梯关门指令”的信号的地址信息
        type: "4x",
        number: 3,
        mark: "1楼电梯关门指令"
    },
    liftClose2: {            // “电梯关门指令”的信号的地址信息
        type: "4x",
        number: 7,
        mark: "2楼电梯关门指令"
    },
    liftClose3: {            // “电梯关门指令”的信号的地址信息
        type: "4x",
        number: 11,
        mark: "3楼电梯关门指令"
    },
    liftClose4: {            // “电梯关门指令”的信号的地址信息
        type: "4x",
        number: 15,
        mark: "4楼电梯关门指令"
    },
    liftClose5: {            // “电梯关门指令”的信号的地址信息
        type: "4x",
        number: 19,
        mark: "5楼电梯关门指令"
    },
    liftOpened1: {            // “电梯开门完成”的信号的地址信息
        type: "3x",
        number: 0,
        mark: "1楼电梯开门完成"
    },
    liftOpened2: {            // “电梯开门完成”的信号的地址信息
        type: "3x",
        number: 2,
        mark: "2楼电梯开门完成"
    },
    liftOpened3: {            // “电梯开门完成”的信号的地址信息
        type: "3x",
        number: 4,
        mark: "3楼电梯开门完成"
    },
    liftOpened4: {            // “电梯开门完成”的信号的地址信息
        type: "3x",
        number: 6,
        mark: "4楼电梯开门完成"
    },
    liftOpened5: {            // “电梯开门完成”的信号的地址信息
        type: "3x",
        number: 8,
        mark: "5楼电梯开门完成"
    },
    liftClosed1: {            // “电梯关门完成”的信号的地址信息
        type: "3x",
        number: 1,
        mark: "1楼电梯关门完成"
    },
    liftClosed2: {            // “电梯关门完成”的信号的地址信息
        type: "3x",
        number: 3,
        mark: "2楼电梯关门完成"
    },
    liftClosed3: {            // “电梯关门完成”的信号的地址信息
        type: "3x",
        number: 5,
        mark: "3楼电梯关门完成"
    },
    liftClosed4: {            // “电梯关门完成”的信号的地址信息
        type: "3x",
        number: 7,
        mark: "4楼电梯关门完成"
    },
    liftClosed5: {            // “电梯关门完成”的信号的地址信息
        type: "3x",
        number: 9,
        mark: "5楼电梯关门完成"
    }
}

function boot() {
    jj.registerHandler("POST", "/script-api/Orders", "Orders", false)//WMS发送运单至RDS
    // jj.registerHandler("POST", "/script-api/qrResult", "qrResult", false)//WMS发送二维码对比结果至RDS
    jj.registerHandler("POST", "/script-api/elevatorsCount", "elevatorsCount", false)//WMS发送可用的电梯数量至RDS
    jj.registerHandler("POST", "/script-api/questions", "questions", false)//WMS发送问题件摆放区库位状态
    jj.registerHandler("POST", "/script-api/localtionState", "localtionState", false); //模拟wms接口
    jj.registerHandler("POST", "/script-api/qrCodeInformation", "qrCodeInformation", false); //模拟wms接口
    jj.registerTaskEventFunction("taskStopped")//任务异常结束处理
    jj.defineScheduledFunctions(true, 5000, 2000, "executeOrder", [])
    jj.putCacheParam(lift1[0], "0")
    jj.putCacheParam(lift3[0], "0")
    // jj.defineScheduledFunctions(true, 5000, 2000, "pickUpStart", []);
    // jj.defineScheduledFunctions(true, 5000, 2000, "warehousingPickUpStart", []);
}

function test() {
    liftOpen("ALift", 1, "")
}

function localtionState(param: string) {
    try {
        var body = JSON.parse(param)
        var siteId = body.name
        var state = body.state
        if (state == 1) {
            jj.setFilledWithContentBySiteId(siteId, "")
        } else {
            jj.setUnfilledBySiteId(siteId)
        }
        let resp: { message: string, code: number } = { message: "请求成功", code: 0 };
        return { code: 201, body: JSON.stringify(resp) }
    } catch (error) {
        let resp: { message: string, code: number } = { message: "请求失败", code: 400 };
        return { code: 400, body: JSON.stringify(resp) }
    }
}

function qrCodeInformation(param: string) {
    let resp: { message: string, code: number } = { message: "OK", code: 0 };
    return { code: 201, body: JSON.stringify(resp) }
}

function taskStopped(param: string) {
    const paramObject = JSON.parse(param)
    const taskRecord = paramObject["taskRecord"]
    const taskLabel = taskRecord["defLabel"]
    if (taskLabel != "ex-warehouse" && taskLabel != "warehousing") {
        return
    }
    const inputParams: any[] = JSON.parse(taskRecord["inputParams"])
    var floorStr = getInputParamsValue(inputParams, "siteFloor")
    var floor = floorStr.substring(0, 1)
    if (parseInt(floor) == 1) {
        var isFull = jj.getCacheParam(lift3[0])
        jj.putCacheParam(lift3[0], (parseInt(isFull) - 1) + "")
    } else {
        var isFull = jj.getCacheParam(lift1[0])
        jj.putCacheParam(lift1[0], (parseInt(isFull) - 1) + "")
    }
}

//WMS发送运单至RDS,api
function Orders(param: string) {
    //运单存队列
    var res: boolean = jj.receiveOrder(param);
    if (res) {
        let resp: { message: string, code: number } = { message: "请求成功", code: 0 };
        return { code: 201, body: JSON.stringify(resp) }
    }
    let resp: { message: string, code: number } = { message: "请求失败", code: 400 };
    return { code: 400, body: JSON.stringify(resp) }
}

//运行出库/入库任务
function executeOrder() {
    var number = Math.random();
    if (number <= 0.5) {
        var orderListStr = jj.jdbcQuery("select * from t_windthirdorder where status = 0 and type = 'ex-warehouse'")
        if (orderListStr == "[]") return
        var isFull = jj.getCacheParam(lift1[0])
        if (isFull == null) {
            jj.putCacheParam(lift1[0], "0")
            isFull = jj.getCacheParam(lift1[0])
        }
        var count = parseInt(isFull)
        liftCount = parseInt(jj.getCacheParam("ex-warehouse-count"))
        if (liftCount != 1 && liftCount != 2) return
        if (liftCount == 1 && count == liftSiteCount) {
            return
        } else if (count == 2 * liftSiteCount) return
        jj.putCacheParam(lift1[0], (count + 1) + "")
        jj.scriptLog("INFO", "executeOrder", "出库运单数据:" + orderListStr)
        var orderJson: Array<any> = JSON.parse(orderListStr);
        if (orderJson != null && orderJson.length > 0) {
            var orderJson: Array<any> = JSON.parse(orderListStr);
            var order = orderJson[0];
            var id = order["id"]
            let req = {
                taskLabel: "ex-warehouse",
                inputParams: JSON.stringify(getInputParams(order))
            }
            jj.newThreadToSetOrder(JSON.stringify(req))
        }
    } else {
        var orderListStr = jj.jdbcQuery("select * from t_windthirdorder where status = 0 and type = 'warehousing'")
        if (orderListStr == "[]") return
        var liftCount = parseInt(jj.getCacheParam("ex-warehouse-count"))
        if (liftCount != 1) return
        var isFull = jj.getCacheParam(lift3[0])
        if (isFull == null) {
            jj.putCacheParam(lift3[0], "0")
            isFull = jj.getCacheParam(lift3[0])
        }
        var count = parseInt(isFull)
        if (count == liftSiteCount) return
        jj.putCacheParam(lift3[0], (count + 1) + "")
        jj.scriptLog("INFO", "executeOrder", "入库运单数据:" + orderListStr)
        var orderJson: Array<any> = JSON.parse(orderListStr);
        if (orderJson != null && orderJson.length > 0) {
            var orderJson: Array<any> = JSON.parse(orderListStr);
            var order = orderJson[0];
            var id = order["id"]
            let req = {
                taskLabel: "warehousing",
                inputParams: JSON.stringify(getInputParams(order))
            }
            jj.newThreadToSetOrder(JSON.stringify(req))
        }
    }
    jj.jdbcSave("update t_windthirdorder set status = 1 where id = ?", [id])
}

//得到订单参数
function getInputParams(order: any) {
    var orderParams = order["params"]
    var orderParamsJson = JSON.parse(orderParams)
    var orderName = orderParamsJson["name"];
    var type = orderParamsJson["type"];
    var partNumber = orderParamsJson["partNumber"];
    var startingPoint = orderParamsJson["startingPoint"];
    var destinations = orderParamsJson["destinations"];
    let inputParams = {
        startingPoint: startingPoint,
        destinations: destinations,
        orderName: orderName,
        partNumber: partNumber,
        orderType: type,
        siteFloor: getFloor(startingPoint),
        siteArea: getArea(startingPoint),
        siteFloorArea: getFloorArea(startingPoint),
        liftQRSite: getFloor(startingPoint) + "-QRSite",
        liftSafeSite: getFloor(startingPoint) + "-SafeSite"
    }
    return inputParams
}

//根据运单起始点解析楼层 :ZH-3f-unqualified-10001
function getFloor(startingPoint: string) {
    var arr = startingPoint.split("-");
    var floor = arr[0] + "-" + arr[1];
    return floor;
}

//根据运单起始点解析区域
function getArea(startingPoint: string) {
    var arr = startingPoint.split("-");
    var area = arr[2];
    return area;
}

//根据运单名解析楼层+区域
function getFloorArea(startingPoint: string) {
    var arr = startingPoint.split("-");
    var addr = arr[0];
    var floor = arr[1];
    var area = arr[2];
    return addr + "-" + floor + "-" + area;
}

//RDS发送库位清空指令至WMS(event function)
function sendSiteStatus(param: string) {
    console.log("RDS发送库位清空指令至WMS");
    try {
        var paramJson = JSON.parse(param);
        var startSite = paramJson["eventData"];
        jj.getLogger().info("sendSiteStatus startSite:" + startSite)
        let req: { name: string, state: string } = { name: startSite, state: "0" }//1空位占用，0库位空闲

        var retry = 0;
        var isOk: boolean = false;
        while (retry < 5) {
            retry++;
            var result = jj.requestPost(localtionStateUrl, JSON.stringify(req));
            var resultJson = JSON.parse(result);
            var code = resultJson["code"];
            var body = resultJson["body"];
            console.log(code + " " + body)
            if (code == "201") {
                var bodyCode = JSON.parse(body)["code"]
                console.log(bodyCode)
                if (bodyCode == "0") {
                    jj.getLogger().info("RDS send clearSite state success")
                    isOk = true;
                    break
                }
            }
        }
        if (!isOk) {
            throw new Error("RDS send clearSite state failed")
        }
    } catch (error) {
        jj.getLogger().error("RDS send clearSite state failed", error)
        throw new Error("RDS send clearSite state failed");
    }
}

//扫码器扫码货物->RDS向WMS发送二维码
function QRProssor(param: string) {
    console.log("扫码器扫码货物->RDS向WMS发送二维码")
    try {
        var paramJson = JSON.parse(param);
        //RDS向扫码器发送参数初始化指令
        console.log("扫码器扫码货物->RDS向WMS发送二维码:qrIp=" + plcConfig.qrIp)
        var initRes = jj.writeSingleModbusValue(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrInitWrite.type, plcConfig.qrInitWrite.number, 1);
        console.log("扫码器扫码货物->RDS向WMS发送二维码:initRes=" + initRes)
        if (!initRes) {
            jj.getLogger().error("QR param init failed", initRes);
            throw new Error("QR param init failed, initRes=" + initRes)
        }

        var taskRecordId = paramJson["taskRecord"]["id"];

        var status: number = 1000;
        //查询扫码器参数初始化是否完毕
        var initOverRes = -1;

        while (status == 1000) {
            status = getStatus(taskRecordId)
            //二维码识别是否完成
            initOverRes = jj.readSingleModbusValue(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrInitRead.type, plcConfig.qrInitRead.number)
            if (initOverRes == 1) {
                break
            } else {
                jj.sleep(2000)
            }
        }

        if (initOverRes == null || initOverRes != 1) {
            jj.getLogger().error("QR param initOver failed", initOverRes);
            throw new Error("QR param initOver failed, initOverRes=" + initOverRes)
        }

        //触发扫码
        var QrRes = jj.writeSingleModbusValue(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrWrite.type, plcConfig.qrWrite.number, 1)
        if (!QrRes) {
            jj.getLogger().error("Qr failed, QrRes", QrRes);
            throw new Error("QR failed, QrRes=" + QrRes)
        }

        //二维码识别是否完成
        var QrRegnizeRes = -1;
        while (status == 1000) {
            status = getStatus(taskRecordId)
            //二维码识别是否完成
            QrRegnizeRes = jj.readSingleModbusValue(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrRead.type, plcConfig.qrRead.number)
            if (QrRegnizeRes == 1) {
                break
            } else {
                jj.sleep(2000)
            }
        }

        if (QrRegnizeRes == null || QrRegnizeRes != 1) {
            jj.getLogger().error("QrRegnize success, QrRegnizeRes=", QrRegnizeRes);
            throw new Error("QrRegnize failed, QrRegnizeRes=" + QrRegnizeRes)
        }

        //查询二维码字符串
        var QrcodeRes = jj.readMultiHoldingRegisters(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrcode.number, plcConfig.qrcode.count, 2)

        if (QrcodeRes == null || QrcodeRes == "") {
            jj.getLogger().error("QrcodeRes failed, QrcodeRes is empty", QrcodeRes);
            throw new Error("QrcodeRes failed, QrcodeRes is empty")
        }

        //清空信号
        jj.writeSingleModbusValue(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrInitWrite.type, plcConfig.qrInitWrite.number, 0);
        jj.writeSingleModbusValue(plcConfig.qrIp, plcConfig.qrPort, plcConfig.qrSlaveId, plcConfig.qrWrite.type, plcConfig.qrWrite.number, 0)

        // //RDS发送二维码信息至WMS
        var orderName = paramJson["eventData"];
        let req: {
            name: string,
            code: string
        }
            = {
            name: orderName,
            code: QrcodeRes
        }
        var qrResult = ""
        var retry = 0;
        var resp = "";
        var code = "";
        var bodyCode = "";
        while (retry < 3) {//失败重试3次
            retry++;
            console.log("----" + JSON.stringify(req))
            resp = jj.requestPost(qrCodeInformationUrl, JSON.stringify(req));
            console.log("----" + resp)
            var respJson = JSON.parse(resp);
            code = respJson["code"];
            bodyCode = JSON.parse(respJson["body"])["code"];
            qrResult = JSON.parse(respJson["body"])["message"];
            if (code == "201" && bodyCode == "0") {
                break;
            }
        }

        if (code != "201" || bodyCode != "0") {
            throw new Error("RDS send QR to WMS failed,resp=" + resp)
        }

        if (qrResult == null || qrResult == "") {
            throw new Error("RDS query qrResult failed,qrResult=" + qrResult)
        }
        let outputParams = {
            qrResult: qrResult
        }
        //对比结果作为任务输入参数
        return { result: JSON.stringify(outputParams) }
    } catch (error) {
        jj.clearExtParam(orderName)
        jj.getLogger().error("QRProssor error", error)
        throw new Error("QRProssor error:" + error);
    }
}

//打开电梯，将货物放到电梯库位
function goLiftAndFill(param: string) {
    console.log("打开电梯，将货物放到电梯库位")
    try {
        var paramJson = JSON.parse(param);
        var taskRecordId = paramJson["taskRecord"]["id"];
        //查询电梯可用数量     
        var status = 1000
        var liftCount = -1
        while (status == 1000) {
            status = getStatus(taskRecordId)
            liftCount = parseInt(jj.getCacheParam("ex-warehouse-count"))
            if (liftCount == 1 || liftCount == 2) {
                break
            } else {
                jj.sleep(2000)
            }
        }
        if (liftCount >= 2) {
            // 可用电梯数量=2，标记入库电梯作为出库电梯使用
            jj.writeSingleModbusValue(plcConfig.ALiftIp, plcConfig.ALiftPort, plcConfig.qrSlaveId, plcConfig.remarkLift.type, plcConfig.remarkLift.number, 1)
            //选择电梯及库位
            var res = chooseAndUpdateIdleSite(lift2);
            var status = 1000;
            while (status == 1000 && JSON.parse(res.result).liftIdleSite == null) {
                jj.sleep(2000)
                status = getStatus(taskRecordId)
                var res = chooseAndUpdateIdleSite(lift2);
            }
            console.log("选择电梯及库位:res=" + JSON.stringify(res))
            //开电梯
            var lift = JSON.parse(res.result).liftIdleSite.split("-")[0];
            var floor = paramJson["eventData"][1];

            var floorStr = floor.split("-")[1]
            console.log("开门楼层:" + floor)
            floor = floorStr.substring(0, 1);
            liftOpen(lift, parseInt(floor), taskRecordId)
            jj.putCacheParam(JSON.parse(res.result).liftIdleSite, paramJson["eventData"][2]);

            return res;
        }
        else if (liftCount == 1) {
            //选择电梯及库位
            var res = chooseAndUpdateIdleSite(lift1);
            var status = 1000;
            while (status == 1000 && JSON.parse(res.result).liftIdleSite == null) {
                jj.sleep(2000)
                status = getStatus(taskRecordId)
                res = chooseAndUpdateIdleSite(lift1);
            }
            console.log("选择电梯及库位:res=" + JSON.stringify(res))
            //开电梯
            var lift = JSON.parse(res.result).liftIdleSite.split("-")[0];
            var floor = paramJson["eventData"][1];

            console.log("开门楼层:" + floor)
            var floorStr = floor.split("-")[1]
            floor = floorStr.substring(0, 1);
            liftOpen(lift, parseInt(floor), taskRecordId)
            jj.putCacheParam(JSON.parse(res.result).liftIdleSite, paramJson["eventData"][2]);

            return res;
        }
        else {
            throw new Error("no lift available")
        }
    } catch (error) {
        jj.getLogger().error("goLiftAndFill error", error)
        throw new Error("goLiftAndFill error:" + error);
    }

}

//装货至电梯完毕，电梯关门
function filledOver(param: string) {
    console.log("装货至电梯完毕，电梯关门")
    var paramJson = JSON.parse(param)
    var taskRecordId = paramJson["taskRecord"]["id"];
    try {
        var lift = paramJson["eventData"][0];
        //发送关门电梯层数指令
        var floor = paramJson["eventData"][1];
        var floorStr = floor.split("-")[1]
        floor = floorStr.substring(0, 1);
        liftClose(lift, parseInt(floor), taskRecordId);
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }
}

//一楼机器人取货初始化
function pickUpStart() {
    try {
        //减少电梯台数日志打印
        var siteListStr1 = jj.getUnlockAreaFilledSite(lift1, 1, 0);
        var siteListStr2 = jj.getUnlockAreaFilledSite(lift3, 1, 0);
        if (siteListStr1 == null && siteListStr2 == null)
            return;
        if (siteListStr2 == null) {
            var siteList1 = JSON.parse(siteListStr1);
            if (siteList1.length != liftSiteCount) return
        } else if (siteListStr1 == null) {
            var siteList2 = JSON.parse(siteListStr2);
            if (siteList2.length != liftSiteCount) return
        } else {
            var siteList1 = JSON.parse(siteListStr1);
            var siteList2 = JSON.parse(siteListStr2);
            if (siteList1.length != liftSiteCount && siteList2.length != liftSiteCount) return
        }
        var liftCount = -1
        liftCount = parseInt(jj.getCacheParam("ex-warehouse-count"))
        var lift: string = "";
        if (liftCount >= 2) {
            if (siteListStr2 == null) {
                lift = lift1[0]
            } else if (siteListStr1 == null) {
                lift = lift3[0]
            } else {
                lift = lift1[0]
            }
        }
        else if (liftCount == 1) {
            lift = lift1[0]
        }
        else {
            throw new Error("No lift available");
        }
        jj.getLogger().info("all lift sites is full,notice 1 floor agv to take");
        var inputParams = setPickUpSite(lift, 1);
        if (inputParams == null)
            return;
        console.log("一楼机器人取货初始化");
        var taskRecordId = jj.createUuid();
        var req = {
            taskLabel: "ex-warehouse-2",
            inputParams: inputParams.result,
            taskRecordId: taskRecordId
        };
        jj.newThreadToSetOrder(JSON.stringify(req));
        if (liftCount >= 2) {
            liftOpen(lift, 1, taskRecordId);
        }
        else if (liftCount == 1) {
            liftOpen(lift1[0], 1, taskRecordId);
        }
    }
    catch (error) {
        jj.getLogger().error("filledOver error", error);
        throw new Error("filledOver error:" + error);
    }
}

//任务封口
function markComplete(param: string) {
    console.log("电梯装满，2~5楼机器人任务封口")
    var paramJson = JSON.parse(param);
    var taskRecordId = paramJson["taskRecord"]["id"];
    jj.markComplete(taskRecordId)
}

//一楼机器人取货
function pickUp(param: string) {
    console.log("一楼机器人取货")
    var paramJson = JSON.parse(param)
    try {
        var curPickUpSite = paramJson["eventData"][0]
        var pickUpSiteArea = paramJson["eventData"][1]
        console.log("一楼机器人取货完毕，更新电梯库位:" + curPickUpSite)
        jj.updateFilledStatusBySiteId(curPickUpSite, 0);//更新为无货物状态
        //重新设置下次取货的库位
        return setPickUpSite(pickUpSiteArea, 0);
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }

}

//设置一楼机器人从电梯取货的库位
function setPickUpSite(param: string, pcikupstart: number) {
    try {
        var liftCount = -1
        liftCount = parseInt(jj.getCacheParam("ex-warehouse-count"))
        var siteStr: string = "";
        var lift: Array<any> = [];
        if (liftCount >= 2) {
            lift.push(param)
            siteStr = jj.getAreaFilledSite(lift, 1);
        } else if (liftCount == 1) {
            siteStr = jj.getAreaFilledSite(lift1, 1);
            lift = lift1;
        }
        var site: Array<any> = JSON.parse(siteStr);
        if (site.length == 0) {
            if (pcikupstart == 1) {
                return
            }
            var ListStr = jj.getAreaFilledSite(lift, 0);
            var Listsite: Array<any> = JSON.parse(ListStr)
            Listsite.forEach(function (element) {
                jj.jdbcSave("UPDATE t_worksite SET locked = 0 WHERE site_id = ?", element.siteId);
            });
            var isFull = jj.getCacheParam(lift1[0])
            jj.putCacheParam(lift1[0], (parseInt(isFull) - liftSiteCount) + "")
            jj.getLogger().error("all lift sites is empty", "")
            return;
        }
        let pickUpSite = {
            pickUpSite: site[0]["siteId"], //site已倒序排列，第一个是电梯门口右边的库位，取第一个作为一楼机器人的初始取货库位
            pickUpSiteSize: site.length,
            pickUpSiteArea: site[0]["siteId"].split("-")[0],
            destinations: jj.getCacheParam(site[0]["siteId"]),
            siteFloor: getFloor(jj.getCacheParam(site[0]["siteId"]))
        }
        var floor = pickUpSite.destinations;
        var floorStr = floor.split("-")[1];
        floor = floorStr.substring(0, 1);
        if (parseInt(floor) !== 1)
            return;
        jj.clearCacheParam(site[0]["siteId"])
        jj.jdbcSave("UPDATE t_worksite SET locked = 1 WHERE site_id = ?", pickUpSite.pickUpSite);
        //设置一楼机器人取货的库位
        console.log("设置一楼机器人从电梯取货的库位:" + JSON.stringify(pickUpSite))
        return { result: JSON.stringify(pickUpSite) };
    } catch (error) {
        return
    }
}

//一楼电梯关门，取货结束
function pickUpOver(param: string) {
    console.log("一楼电梯关门，取货结束")
    try {
        //发送关门电梯层数指令
        var liftCount = 0;
        liftCount = parseInt(jj.getCacheParam("ex-warehouse-count"))
        var lift: Array<any> = []
        var paramJson = JSON.parse(param)
        var taskRecordId = paramJson["taskRecord"]["id"];
        if (liftCount >= 2) {
            var pickUpSiteArea = paramJson["eventData"]
            console.log(pickUpSiteArea + "关门指令")
            liftClose(pickUpSiteArea, 1, taskRecordId);
            lift.push(pickUpSiteArea);
            var ListStr = jj.getAreaFilledSite(lift, 0)
            var Listsite: Array<any> = JSON.parse(ListStr)
            Listsite.forEach(element => {
                jj.jdbcSave("UPDATE t_worksite SET locked = 0 WHERE site_id = ?", element.siteId);
            });
        } else if (liftCount == 1) {
            console.log(lift1[0] + "关门指令")
            liftClose(lift1[0], 1, taskRecordId);
            var ListStr = jj.getAreaFilledSite(lift1, 0)
            var Listsite: Array<any> = JSON.parse(ListStr)
            Listsite.forEach(element => {
                jj.jdbcSave("UPDATE t_worksite SET locked = 0 WHERE site_id = ?", element.siteId);
            });
        }
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }
}

//WMS发送二维码对比结果至RDS,api
function qrResult(param: string) {
    try {
        var paramJson = JSON.parse(param);
        var orderName = paramJson["name"];
        var value = paramJson["value"];
        jj.putCacheParam(orderName, value);

        let resp: { message: string, code: number } = { message: "请求成功", code: 0 };
        return { code: 201, body: JSON.stringify(resp) }

    } catch (error) {
        jj.getLogger().error("qrResult error", error)
        let resp: { message: string, code: number } = { message: "请求失败:" + error, code: 400 };
        return { code: 400, body: JSON.stringify(resp) }
    }

}

//获取问题件区空闲状态的库位并设置为输入参数
function chooseIdleSite(area: string) {
    console.log("获取问题件区空闲状态的库位并设置为输入参数")
    var paramJson = JSON.parse(area)
    try {
        var floor = paramJson["eventData"];
        var taskRecordId = paramJson["taskRecord"]["id"];
        var siteIdLike = floor + "-" + unqualifiedArea;
        var floorStr = floor.split("-")[1];
        floor = floorStr.substring(0, 1);
        if (parseInt(floor) == 1) {
            var isFull = jj.getCacheParam(lift3[0])
            jj.putCacheParam(lift3[0], (parseInt(isFull) - 1) + "")
        } else {
            var isFull = jj.getCacheParam(lift1[0])
            jj.putCacheParam(lift1[0], (parseInt(isFull) - 1) + "")
        }
        var arr: Array<string> = []
        arr.push(siteIdLike)
        var status = 1000;
        var siteListStr = null;
        while (status == 1000) {
            status = getStatus(taskRecordId);
            siteListStr = jj.getAreaFilledSite(arr, 0);
            if (siteListStr != null) {
                break
            }
            jj.sleep(2000)
        }
        if (siteListStr == null) {
            jj.getLogger().error("unqualifiedArea is full,can't fill", "");
            return;
        }
        var siteList = JSON.parse(siteListStr)
        let idleSite = {
            idleUnqualifiedSite: siteList[0]["siteId"]
        }
        return { result: JSON.stringify(idleSite) }
    } catch (error) {
        jj.getLogger().error("chooseIdleSite error", error)
        throw new Error("chooseIdleSite error:" + error);
    }
}

//获取电梯空闲状态的库位，并更新为有货状态
function chooseAndUpdateIdleSite(area: Array<string>) {
    console.log("获取电梯空闲状态的库位，并更新为有货状态")
    try {
        var site = jj.chooseAndUpdateIdleSite(area);
        if (site == null) {
            let idleSite = {
                liftIdleSite: null,
                liftIdleArea: null
            }

            jj.getLogger().info("lift sites was full,can't fill more, notice 1 floor agv to take")
            console.log("电梯已满，通知一楼取货")
            return { result: JSON.stringify(idleSite) };
        }
        var siteJson = JSON.parse(site);
        let idleSite = {
            liftIdleSite: siteJson["siteId"],
            liftIdleArea: siteJson["siteId"].split("-")[0]
        }

        return { result: JSON.stringify(idleSite) };
    } catch (error) {
        jj.getLogger().error("chooseAndUpdateIdleSite error", error)
        throw new Error("chooseAndUpdateIdleSite error:" + error);
    }

}

//发送库位占用状态至WMS
function sendSiteStatusToWms(param: string) {
    try {
        var paramJson = JSON.parse(param);
        var site = paramJson["eventData"];
        jj.getLogger().info("sendSiteStatus startSite:" + site)
        let req: { name: string, state: string } = { name: site, state: "1" }//1库位占用，0库位空闲

        //更新库位状态
        var floor = paramJson["eventData"][1];
        jj.updateFilledStatusBySiteId(site, 1)

        //发送库位状态至WMS
        var retry = 0;
        var isOk: boolean = false;
        var result = "";
        while (retry < 5) {
            retry++;
            result = jj.requestPost(localtionStateUrl, JSON.stringify(req));
            var resultJson = JSON.parse(result);
            var code = resultJson["code"];
            var body = JSON.parse(resultJson["body"]);
            if (code == "201") {
                var bodyCode = body["code"]
                if (bodyCode == "0") {
                    jj.getLogger().info("RDS send filled site state success")
                    isOk = true;
                    break
                }
            }
        }
        if (!isOk) {
            jj.getLogger().error("sendSiteStatusToWms error", result);
            throw new Error("RDS send filled site state to wms failed,result=" + result)
        }
    } catch (error) {
        jj.getLogger().error("sendSiteStatusToWms error", error)
        throw new Error("RDS send filled site state to wms failed,error=" + error);

    }
}

//WMS推送可用的电梯数量至RDS,api
function elevatorsCount(param: string) {
    try {
        var paramJson = JSON.parse(param);
        var value = paramJson["value"];
        var siteListStr = jj.getUnlockAreaFilledSite(lift3, 1, 0);
        if (siteListStr != null) {
            var siteList = JSON.parse(siteListStr)
            if (siteList.length != liftSiteCount) {
                let resp: { message: string, code: number } = { message: "入库电梯有货物，请清空", code: 0 };
                return { code: 400, body: JSON.stringify(resp) }
            }
        }
        jj.putCacheParam("ex-warehouse-count", value);
        let resp: { message: string, code: number } = { message: "请求成功", code: 0 };
        return { code: 201, body: JSON.stringify(resp) }
    } catch (error) {
        jj.getLogger().error("elevatorsCount error", error)
        let resp: { message: string, code: number } = { message: "请求失败:" + error, code: 400 };
        return { code: 400, body: JSON.stringify(resp) }
    }


}

//电梯开门
function liftOpen(lift: string, floor: number, taskRecordId: string) {

    console.log("liftOpen floor=" + floor + ",lift=" + lift)
    console.log("modbus.lift.liftOpenFloor" + floor + ".slaveId")
    var ip: any = getIp(lift)
    var port: any = getPort(lift)
    var slaveId: any = getSlaveId(lift)
    var liftOpenFloor: any = getLiftOpenFloor(floor)
    // 发送电梯开门楼层指令
    jj.writeSingleModbusValue(ip, port, slaveId, liftOpenFloor.type, liftOpenFloor.number, floor)
    //发送电梯开门指令
    var liftOpen: any = getLiftOpen(floor)
    jj.writeSingleModbusValue(ip, port, slaveId, liftOpen.type, liftOpen.number, 1)
    var status: number = 1000
    var openRes = -1;
    var liftOpend: any = getLiftOpend(floor)
    while (status == 1000) {
        status = getStatus(taskRecordId)
        //查询开门到位
        openRes = jj.readSingleModbusValue(ip, port, slaveId, liftOpend.type, liftOpend.number)
        if (openRes == 1) {
            break;
        } else {
            jj.sleep(2000)
        }
    }

    //清空信号
    jj.writeSingleModbusValue(ip, port, slaveId, liftOpenFloor.type, liftOpenFloor.number, 0)
    jj.writeSingleModbusValue(ip, port, slaveId, liftOpen.type, liftOpen.number, 0)

    if (openRes == null || openRes != 1) {
        throw new Error("RDS query openOnefloorDoor failed,openRes=" + openRes)
    }

}

//电梯关门
function liftClose(lift: string, floor: number, taskRecordId: string) {

    console.log("liftClose floor=" + floor + ",lift=" + lift)
    var ip: any = getIp(lift)
    var port: any = getPort(lift)
    var slaveId: any = getSlaveId(lift)
    //发送关门电梯层数指令
    var liftCloseFloor: any = getLiftCloseFloor(floor)
    jj.writeSingleModbusValue(ip, port, slaveId, liftCloseFloor.type, liftCloseFloor.number, floor)
    //发送电梯关门指令
    var liftClose: any = getLiftClose(floor)
    jj.writeSingleModbusValue(ip, port, slaveId, liftClose.type, liftClose.number, 1)
    var status: number = 1000
    var closeRes = -1
    var liftClosed: any = getLiftClosed(floor)
    while (status == 1000) {
        status = getStatus(taskRecordId)
        //查询关门到位
        closeRes = closeRes = jj.readSingleModbusValue(ip, port, slaveId, liftClosed.type, liftClosed.number)
        if (closeRes == 1) {
            break;
        } else {
            jj.sleep(2000)
        }
    }

    //清空信号
    jj.writeSingleModbusValue(ip, port, slaveId, liftCloseFloor.type, liftCloseFloor.number, 0)
    jj.writeSingleModbusValue(ip, port, slaveId, liftClose.type, liftClose.number, 0)

    if (closeRes == null || closeRes != 1) {
        throw new Error("RDS query closeDoor failed,closeRes=" + closeRes)
    }
}

function getIp(lift: string) {
    if (lift == "ALift") {
        return plcConfig.ALiftIp
    } else if (lift == "BLift") {
        return plcConfig.BLiftIp
    }
}

function getPort(lift: string) {
    if (lift == "ALift") {
        return plcConfig.ALiftPort
    } else if (lift == "BLift") {
        return plcConfig.BLiftPort
    }
}

function getSlaveId(lift: string) {
    if (lift == "ALift") {
        return plcConfig.ALiftSlaveId
    } else if (lift == "BLift") {
        return plcConfig.BLiftSlaveId
    }
}

function getLiftOpenFloor(floor: number) {
    if (floor == 1) {
        return plcConfig.liftOpenFloor1
    } else if (floor == 2) {
        return plcConfig.liftOpenFloor2
    } else if (floor == 3) {
        return plcConfig.liftOpenFloor3
    } else if (floor == 4) {
        return plcConfig.liftOpenFloor4
    } else if (floor == 5) {
        return plcConfig.liftOpenFloor5
    }
}

function getLiftOpen(floor: number) {
    if (floor == 1) {
        return plcConfig.liftOpen1
    } else if (floor == 2) {
        return plcConfig.liftOpen2
    } else if (floor == 3) {
        return plcConfig.liftOpen3
    } else if (floor == 4) {
        return plcConfig.liftOpen4
    } else if (floor == 5) {
        return plcConfig.liftOpen5
    }
}

function getLiftOpend(floor: number) {
    if (floor == 1) {
        return plcConfig.liftOpened1
    } else if (floor == 2) {
        return plcConfig.liftOpened2
    } else if (floor == 3) {
        return plcConfig.liftOpened3
    } else if (floor == 4) {
        return plcConfig.liftOpened4
    } else if (floor == 5) {
        return plcConfig.liftOpened5
    }
}

function getLiftCloseFloor(floor: number) {
    if (floor == 1) {
        return plcConfig.liftCloseFloor1
    } else if (floor == 2) {
        return plcConfig.liftCloseFloor2
    } else if (floor == 3) {
        return plcConfig.liftCloseFloor3
    } else if (floor == 4) {
        return plcConfig.liftCloseFloor4
    } else if (floor == 5) {
        return plcConfig.liftCloseFloor5
    }
}

function getLiftClose(floor: number) {
    if (floor == 1) {
        return plcConfig.liftClose1
    } else if (floor == 2) {
        return plcConfig.liftClose2
    } else if (floor == 3) {
        return plcConfig.liftClose3
    } else if (floor == 4) {
        return plcConfig.liftClose4
    } else if (floor == 5) {
        return plcConfig.liftClose5
    }
}

function getLiftClosed(floor: number) {
    if (floor == 1) {
        return plcConfig.liftClosed1
    } else if (floor == 2) {
        return plcConfig.liftClosed2
    } else if (floor == 3) {
        return plcConfig.liftClosed3
    } else if (floor == 4) {
        return plcConfig.liftClosed4
    } else if (floor == 5) {
        return plcConfig.liftClosed5
    }
}

//---------------------------入库--------------------------------------------

//打开电梯，将货物放到电梯库位
function warehousingGoLiftAndFill(param: string) {
    console.log("打开电梯，将货物放到电梯库位")
    try {
        var paramJson = JSON.parse(param);
        var taskRecordId = paramJson["taskRecord"]["id"];
        var res = chooseAndUpdateIdleSite(lift3);
        var status = 1000
        while (status == 1000 && JSON.parse(res.result).liftIdleSite == null) {
            jj.sleep(2000)
            status = getStatus(taskRecordId)
            var res = chooseAndUpdateIdleSite(lift3);
        }
        console.log("选择电梯及库位:res=" + JSON.stringify(res))
        //开电梯
        liftOpen(lift3[0], 1, taskRecordId);
        jj.putCacheParam(JSON.parse(res.result).liftIdleSite, paramJson["eventData"]);
        return res;
    } catch (error) {
        jj.getLogger().error("goLiftAndFill error", error)
        throw new Error("goLiftAndFill error:" + error);
    }

}

//装货至电梯完毕，电梯关门
function warehousingfilledOver(param: string) {
    console.log("装货至电梯完毕，电梯关门")
    try {
        var paramJson = JSON.parse(param);
        var taskRecordId = paramJson["taskRecord"]["id"];
        liftClose(lift3[0], 1, taskRecordId)
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }
}

//2~5楼机器人取货初始化
function warehousingPickUpStart() {
    try {
        var siteListStr = jj.getUnlockAreaFilledSite(lift3, 1, 0);
        if (siteListStr === null)
            return;
        var siteList = JSON.parse(siteListStr);
        if (siteList.length !== liftSiteCount)
            return;
        var inputParams = warehousingSetPickUpSite("", 1);
        if (inputParams == null)
            return;
        var floor = JSON.parse(inputParams.result).destinations
        var floorStr = floor.split("-")[1];
        floor = floorStr.substring(0, 1);
        if (parseInt(floor) === 1)
            return;
        console.log("2~5楼机器人取货初始化")
        var taskRecordId = jj.createUuid();
        var req = {
            taskLabel: "warehousing-2",
            inputParams: inputParams.result,
            taskRecordId: taskRecordId
        };
        jj.newThreadToSetOrder(JSON.stringify(req));
        console.log("2~5楼机器人取货初始化");
        liftOpen(lift3[0], parseInt(floor), taskRecordId);
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }
}

//设置2~5楼机器人从电梯取货的库位
function warehousingSetPickUpSite(param: string, warehousingPickUpStart: number) {
    try {
        var siteStr = jj.getAreaFilledSite(lift3, 1);
        var site: Array<any> = JSON.parse(siteStr);
        if (site.length == 0) {
            if (warehousingPickUpStart == 1) {
                return
            }
            var ListStr = jj.getAreaFilledSite(lift3, 0)
            var Listsite: Array<any> = JSON.parse(ListStr)
            Listsite.forEach(element => {
                jj.jdbcSave("UPDATE t_worksite SET locked = 0 WHERE site_id = ?", element.siteId);
            });
            var isFull = jj.getCacheParam(lift3[0])
            jj.putCacheParam(lift3[0], (parseInt(isFull) - liftSiteCount) + "")
            jj.getLogger().error("all lift sites is empty", "")
            return;
        }
        let pickUpSite = {
            pickUpSite: site[0]["siteId"], //site已倒序排列，第一个是电梯门口右边的库位，取第一个作为一楼机器人的初始取货库位
            pickUpSiteSize: site.length,
            pickUpSiteArea: site[0]["area"],
            destinations: jj.getCacheParam(site[0]["siteId"]),
            siteFloor: getFloor(jj.getCacheParam(site[0]["siteId"]))
        }
        var floor = pickUpSite.destinations;
        var floorStr = floor.split("-")[1];
        floor = floorStr.substring(0, 1);
        if (parseInt(floor) === 1)
            return;
        jj.clearCacheParam(site[0]["siteId"])
        // 电梯库位满，开2~5楼电梯
        var taskRecordId = param
        if (taskRecordId != "") {
            jj.scriptLog("INFO", "start", floor);
            liftOpen(lift3[0], parseInt(floor), taskRecordId);
        }
        //设置2~5楼机器人取货的库位
        jj.jdbcSave("UPDATE t_worksite SET locked = 1 WHERE site_id = ?", pickUpSite.pickUpSite);
        console.log("设置2~5楼机器人从电梯取货的库位" + JSON.stringify(pickUpSite))
        return { result: JSON.stringify(pickUpSite) }
    } catch {
        return
    }
}

//2~5楼机器人取货
function warehousingPickUp(param: string) {
    console.log("2~5楼机器人取货")
    var paramJson = JSON.parse(param)
    try {
        var curPickUpSite = paramJson["eventData"]//当前已取货库位
        jj.updateFilledStatusBySiteId(curPickUpSite, 0);//更新为无货物状态
        var taskRecordId = paramJson["taskRecord"]["id"];
        //重新设置下次取货的库位
        return warehousingSetPickUpSite(taskRecordId, 0);
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }

}

//2~5楼电梯关门，取货结束
function warehousingPickUpOver(param: string) {
    console.log("2~5楼电梯关门，取货结束")
    var paramJson = JSON.parse(param)
    try {
        //关电梯
        var floor = paramJson["eventData"];
        var taskRecordId = paramJson["taskRecord"]["id"];
        var floorStr = floor.split("-")[1];
        floor = floorStr.substring(0, 1);
        liftClose(lift3[0], parseInt(floor), taskRecordId)
    } catch (error) {
        jj.getLogger().error("filledOver error", error)
        throw new Error("filledOver error:" + error);
    }
}

//WMS推送库位状态，RDS更新
function questions(param: string) {
    console.log("WMS库位状态:" + param)
    var siteArr: Array<any> = JSON.parse(param);
    for (var i = 0; i < siteArr.length; i++) {
        var siteId = siteArr[i]["name"];
        var state = siteArr[i]["state"];
        jj.updateFilledStatusBySiteId(siteId, state);
    }
    let resp: { message: string, code: number } = { message: "请求成功", code: 0 };
    return { code: 201, body: JSON.stringify(resp) }
}

function getInputParamsValue(inputParams: any[], failedName: string): any {
    return inputParams.find(i => i.name === failedName).defaultValue
}

//查询天风任务状态
function getStatus(taskRecordId: string) {
    var sql = "SELECT `status` FROM t_windtaskrecord WHERE id = " + "'" + taskRecordId + "'"
    return JSON.parse(jj.jdbcQuery(sql))[0].status
}

//modbus数据类型
class ModbusDataType {
    static readonly BINARY: number = 1;
    static readonly TWO_BYTE_INT_UNSIGNED: number = 2;
    static readonly TWO_BYTE_INT_SIGNED: number = 3;
    static readonly TWO_BYTE_INT_UNSIGNED_SWAPPED: number = 22;
    static readonly TWO_BYTE_INT_SIGNED_SWAPPED: number = 23;
    static readonly FOUR_BYTE_INT_UNSIGNED: number = 4;
    static readonly FOUR_BYTE_INT_SIGNED: number = 5;
    static readonly FOUR_BYTE_INT_UNSIGNED_SWAPPED: number = 6;
    static readonly FOUR_BYTE_INT_SIGNED_SWAPPED: number = 7;
    static readonly FOUR_BYTE_INT_UNSIGNED_SWAPPED_SWAPPED: number = 24;
    static readonly FOUR_BYTE_INT_SIGNED_SWAPPED_SWAPPED: number = 25;
    static readonly FOUR_BYTE_FLOAT: number = 8;
    static readonly FOUR_BYTE_FLOAT_SWAPPED: number = 9;
    static readonly FOUR_BYTE_FLOAT_SWAPPED_INVERTED: number = 21;
    static readonly FOUR_BYTE_FLOAT_INVERTED: number = 26;
    static readonly FOUR_BYTE_FLOAT_SWAPPED_SWAPPED: number = 27;
    static readonly EIGHT_BYTE_INT_UNSIGNED: number = 10;
    static readonly EIGHT_BYTE_INT_SIGNED: number = 11;
    static readonly EIGHT_BYTE_INT_UNSIGNED_SWAPPED: number = 12;
    static readonly EIGHT_BYTE_INT_SIGNED_SWAPPED: number = 13;
    static readonly EIGHT_BYTE_FLOAT: number = 14;
    static readonly EIGHT_BYTE_FLOAT_SWAPPED: number = 15;
    static readonly TWO_BYTE_BCD: number = 16;
    static readonly FOUR_BYTE_BCD: number = 17;
    static readonly FOUR_BYTE_BCD_SWAPPED: number = 20;
    static readonly CHAR: number = 18;
    static readonly VARCHAR: number = 19;
}

function agvActionDone(param: string) {
    console.log(param)
}